package com.tansun.easycare.rule.datamodel.service.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.tansun.easycare.rule.utils.ValidationUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.tansun.easycare.modules.sys.utils.UserUtils;
import com.tansun.easycare.rule.common.DataCache;
import com.tansun.easycare.rule.common.DataSetTreeVo;
import com.tansun.easycare.rule.common.model.Bom;
import com.tansun.easycare.rule.common.model.BomField;
import com.tansun.easycare.rule.common.model.Domain;
import com.tansun.easycare.rule.common.model.DomainItem;
import com.tansun.easycare.rule.common.service.DataBomService;
import com.tansun.easycare.rule.datamodel.entity.RuleDataDomain;
import com.tansun.easycare.rule.datamodel.entity.RuleDataparams;
import com.tansun.easycare.rule.datamodel.entity.RuleDataset;
import com.tansun.easycare.rule.datamodel.entity.RuleEnum;
import com.tansun.easycare.rule.datamodel.service.DataModelService;
import com.tansun.easycare.rule.datamodel.service.RuleDataparamsService;
import com.tansun.easycare.rule.datamodel.service.RuleEnumService;
import com.tansun.easycare.rule.utils.MathUtil;
import com.tansun.easycare.rule.utils.ObjectXmlTool;
import com.tansun.rule.utils.MClass;
import com.tansun.rule.utils.MField;
import com.tansun.rule.utils.StringUtils;
import com.tansun.rule.utils.XMLHandler;

@Service
public class ModelImpoter {

    @Autowired
    DataModelService dataModelService;
    @Autowired
    RuleDataparamsService ruleDataparamsService;
    @Autowired
    DataBomService dataBomService;
	@Autowired
	private RuleEnumService ruleEnumService;
	
    private static final String DATE = "Date";
    private static final String DEFAULT_PATTERN = "MM/DD/YYYY";
	private static Logger logger = LoggerFactory.getLogger(ModelImpoter.class);
	
    /**
     * 将Bom对象转化为xml文件
     */
    public static void bomToXml(Map<String, Bom> boms, String path) throws IOException, DocumentException {
        SAXReader reader = new SAXReader();
//		File dsFile = new File(path+Constant.DMFILE);
        File dsFile = new File(path);
        Document document = null;
        Element root = null;
        boolean fileExixt = false;
        if (!dsFile.exists()) {
            document = DocumentHelper.createDocument();
            document.setXMLEncoding("UTF-8");
            root = document.addElement("mapping");
        } else {
            document = reader.read(dsFile);
            root = document.getRootElement();
            fileExixt = true;
        }
        ObjectXmlTool xmlTool = new ObjectXmlTool();
        Bom bom = null;
        Set<String> keys = boms.keySet();
        boolean isNew = true;
        for (String key : keys) {
            bom = boms.get(key);
            Element cls = root.addElement("class");
            cls.addAttribute("id", StringUtils.generateShortUuid());
            cls.addAttribute("name", bom.getName());
            cls.addAttribute("paramType", bom.getParamType());
            cls.addAttribute("chzn", bom.getLabel());
            cls.addAttribute("desc", bom.getDesc());

            for (BomField field : bom.getBomFields()) {
                Element e = cls.addElement("field");
                if (isNew) {
                    e.addAttribute("id", StringUtils.generateShortUuid());
                } else {
                    e.addAttribute("id", field.getId());
                }
                e.addAttribute("name", field.getName());
                e.addAttribute("type", field.getType());
                e.addAttribute("chzn", field.getLabel());
                e.addAttribute("desc", field.getDesc());
                e.addAttribute("domain", field.getDomain());
                e.addAttribute("domainStr", field.getDomainStr());
                e.addAttribute("collection", field.getCollection());
                e.addAttribute("isout", field.getIsout());
                e.addAttribute("pattern", field.getPattern());
                e.addAttribute("mathStr", field.getMathStr());
                e.addAttribute("defaultValue", field.getDefaultValue());
                e.addAttribute("isDerives", field.getIsDerives());
                e.addAttribute("isCollections", field.getIsCollections());
                e.addAttribute("domainId", field.getDomainId());
            }
        }
        writeToXml(document, path);
    }

    /**
     * 将Domain对象转化为xml文件
     */
    public static void domToXml(Map<String, Domain> doms, String path) throws IOException {
        Set<String> keys = doms.keySet();
        Document document = DocumentHelper.createDocument();
        document.setXMLEncoding("UTF-8");
        Element root = document.addElement("mapping");
        Domain dom = null;
        for (String key : keys) {
            dom = doms.get(key);
            Element cls = root.addElement("domain");
            cls.addAttribute("id", dom.getId());
            cls.addAttribute("attrId", dom.getAttrId());
            cls.addAttribute("name", dom.getName());
            cls.addAttribute("chzn", dom.getLabel());
            cls.addAttribute("type", dom.getDataType());
            cls.addAttribute("desc", dom.getDesc());
            for (DomainItem it : dom.getDomainItems()) {
                Element e = cls.addElement("item");
                e.addAttribute("id", StringUtils.generateShortUuid());
                e.addAttribute("name", it.getName());
                e.addAttribute("value", it.getValue());
            }
        }
        writeToXml(document, path);
    }

    /**
     * 保存到文件
     */
    public static void writeToXml(Document document, String path) throws IOException {

        //FileWriter fw = new FileWriter(new File(path));
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("UTF-8");
        XMLWriter output = new XMLWriter(new FileOutputStream(new File(path)), format);
        output.write(document);
        output.close();

    }

    /**
     * 解析上传的Excel文件并保存成xml文件
     * @param file 上传文件对象
     * @param projectCode 项目编码
     * @param datamodelid 数据模型id
     * @param rankRelationId 目录关联id
     * @throws Exception
     */
    public void excelToXml(MultipartFile file, String projectCode, String datamodelid,String userId, String rankRelationId) throws Exception {

        Workbook workbook = null;

        if (file.getOriginalFilename().toLowerCase().endsWith("xlsx")) {
            workbook = new XSSFWorkbook(file.getInputStream());
        } else if (file.getOriginalFilename().toLowerCase().endsWith("xls")) {
            workbook = new HSSFWorkbook(file.getInputStream());
        } else {
            throw new IllegalStateException("文件不是Excel格式");
        }
        if (workbook.getSheetAt(0).getLastRowNum() < 1) {
            throw new Exception("上传失败！数据集为空,请修改！");
        }
        Map<String, Domain> doms = excelToDom(workbook);

        Map<String, Bom> boms = excelToBom(workbook, doms);
        
		List<RuleEnum> ruleenumList = excelToEnum(workbook);

		List<RuleEnum> enumtype = exceltypeToEnum(workbook,userId);

		//查询数据集
        List<DataSetTreeVo> dstvList = dataBomService.findBomListByProjCode(projectCode);
        //数据源于数据集以map形式存储
        Map<String,RuleDataset> mapping = new HashMap<String,RuleDataset>();
        Map<String,RuleDataparams> mappingChild = new HashMap<String,RuleDataparams>();
        for(DataSetTreeVo dstv:dstvList) {
        	if(StringUtils.isEmpty(dstv.getRankRelationId()) || dstv.getRankRelationId().equals(rankRelationId)) {
        		RuleDataset rd = dstv.getDataset();
        		if(StringUtils.isEmpty(datamodelid) || (StringUtils.isNotEmpty(datamodelid) && datamodelid.equals(rd.getDatamodelid()))) {
            		if( !"1".equals(rd.getIsbuiltin()) ) {
    	        		String key1 = rd.getName()+rd.getChzn()+rd.getParamType();
    	        		mapping.put(key1, rd);
    	        		if(dstv.getChildren()!=null) {
    		        		for(DataSetTreeVo dstvc:dstv.getChildren()) {
    		        			RuleDataparams rdp = dstvc.getParam();
    		        			if( !"1".equals(rdp.getIsfuncparam()) ) {
    			        			String key2 = key1 + rdp.getName()+rdp.getChzn();
    			        			mappingChild.put(key2, rdp);
    		        			}
    		        		}
    	        		}
            		}
        		}
        	}
        }
        List<String> rdpIdsList = new ArrayList<String>();//需要删除的ruleDataparams id
        List<RuleDataset> dsList = new ArrayList<RuleDataset>();//需要插入的dataSet
        List<RuleDataparams> paramList = new ArrayList<RuleDataparams>();
        List<RuleDataDomain> domainList = new ArrayList<RuleDataDomain>();
        RuleDataset ds = null;
        for (String key : boms.keySet()) {
            Bom b = boms.get(key);
            ds = new RuleDataset();
            BeanUtils.copyProperties(ds, b);
            ds.setCreateDate(new Date());
            ds.setCreateBy(userId);
            ds.setChzn(b.getLabel());
            ds.setProjectcode(projectCode);
            ds.setId(StringUtils.getUUID());
            ds.setRankRelationId(rankRelationId);
            ds.setDatamodelid(datamodelid);
            String key1 = b.getName()+b.getLabel()+b.getParamType();
            if( mapping.containsKey(key1) ){//数据集是否已经存在
            	ds = mapping.get(key1);
            }else {//不存在，添加
            	dsList.add(ds);
            }
            if (b.getBomFields() == null || b.getBomFields().size() == 0) {
                continue;
            }
            RuleDataparams param = null;
            for (BomField field : b.getBomFields()) {
                param = new RuleDataparams();
                BeanUtils.copyProperties(param, field);
                param.setId(StringUtils.getUUID());
                param.setCreateBy(userId);
                param.setChzn(field.getLabel());
                param.setProjectcode(projectCode);
                param.setDatasetId(ds.getId());
                param.setCreateDate(ds.getCreateDate());
                //数据参数是否已经存在
                String key2 = key1 + field.getName()+field.getLabel();
                if( mappingChild.containsKey(key2) ){
                	RuleDataparams rdp = mappingChild.get(key2);
                	rdpIdsList.add(rdp.getId());//添加需要删除的ruleDataparams id
                }
                paramList.add(param);
                if (StringUtils.isEmpty(param.getDomain()))
                    continue;
                if(doms!=null) {//枚举
	                for (String dk : doms.keySet()) {
	                    Domain d = doms.get(dk);
	                    if (d.getName().equals(param.getDomain())) {
	                        RuleDataDomain rd = null;
	                        param.setDomain(param.getId());
	                        for (DomainItem di : d.getDomainItems()) {
	                            rd = new RuleDataDomain();
	                            rd.setId(StringUtils.getUUID());
	                            rd.setDomainValue(di.getValue());
	                            rd.setName(di.getName());
	                            rd.setDomainId(param.getDomain());
	                            domainList.add(rd);
	                        }
	                    }
	                }
                }
            }
        }
        
        ruleDataparamsService.deleteRuleDataparamsByIds(rdpIdsList);//删除数据参数
//        RuleDataset con = new RuleDataset();
//        con.setProjectcode(projectCode);
//        RuleDataparams con2 = new RuleDataparams();
//        con2.setProjectcode(projectCode);
//        dataModelService.delete(con);
//        ruleDataparamsService.delete(con2);
        
        //插入
        dataModelService.insertBatch(dsList, true);
        ValidationUtils.validate(dsList);
        ruleDataparamsService.insertBatch(paramList, true);
        ValidationUtils.validate(paramList);
        ruleDataparamsService.insertBatchDomains(domainList);
        //缓存清理
        DataCache.paramChange(projectCode);
        DataCache.enumChange(projectCode);
    }
    
    /**
	 * 解析工作表中的RuleEnumType对象
	 */
	public  List<RuleEnum> exceltypeToEnum(Workbook workbook,String userId) {
		if (workbook.getNumberOfSheets() < 5) {
			return null;
		}
		Sheet sheet = workbook.getSheetAt(4);
		Date date = new Date();
		List<RuleEnum> list = new ArrayList<RuleEnum>();
		Row row = null;
		RuleEnum rule = null;
		for (int i = 1; i <= sheet.getLastRowNum(); i++) {
			row = sheet.getRow(i);
			if (row == null) break;

			rule = new RuleEnum();
			rule.setId(getStringCellValue(row.getCell(0)));
			rule.setEnumName(getStringCellValue(row.getCell(1)));
			rule.setEnumCode(getStringCellValue(row.getCell(2)));
			rule.setEnumType("枚举类型管理");
			rule.setCreateBy(userId);
			rule.setUpdateBy(userId);
			rule.setCreateDate(date);
			rule.setUpdateDate(date);
			list.add(rule);
			// 空行结束
			if (StringUtils.isEmpty(rule.getEnumName()) && StringUtils.isEmpty(rule.getEnumCode())) {
				break;
			}

		}
		
		ruleEnumService.insertList(list);
		return list;
	}

	/**
	 * 解析工作表中的RuleEnum对象
	 */
	public  List<RuleEnum> excelToEnum(Workbook workbook) {
		if (workbook.getNumberOfSheets() < 4) {
			return null;
		}
		Sheet sheettype = workbook.getSheetAt(4);
		Sheet sheet = workbook.getSheetAt(3);

		List<RuleEnum> list = new ArrayList<RuleEnum>();
		Row row = null;
		Row rowtype=null;
		RuleEnum rule = null;
		for (int j = 1; j <= sheettype.getLastRowNum(); j++) {
			rowtype = sheettype.getRow(j);
			for (int i = 1; i <= sheet.getLastRowNum(); i++) {
				row = sheet.getRow(i);
				rule = new RuleEnum();
				if (row.getCell(2) == null || row.getCell(2).getStringCellValue().trim().equals(""))
					continue;
				if (row == null) break;
				if (getStringCellValue(row.getCell(3)).equals(getStringCellValue(rowtype.getCell(1)))) {
					rule.setEnumType(getStringCellValue(rowtype.getCell(2)));
					rule.setId(getStringCellValue(row.getCell(0)));
					rule.setEnumName(getStringCellValue(row.getCell(1)));
					rule.setEnumCode(getStringCellValue(row.getCell(2)));
					list.add(rule);
//					ruleEnumService.save(rule);
				}
				
			}
			// 空行结束
			if (rule==null || (StringUtils.isEmpty(rule.getEnumName()) && StringUtils.isEmpty(rule.getEnumCode())
					&& StringUtils.isEmpty(rule.getEnumType()))) {
				break;
			}

		}
		if(list != null && !list.isEmpty()) {
			ruleEnumService.insertList(list);
		}
		return list;
	}

    /**
     * 解析Bom对象
     */
    public static Map<String, Bom> excelToBom(Workbook workbook, Map<String, Domain> doms) throws Exception {
        Map<String, Bom> boms = new HashMap<String, Bom>();
        //1.解析class表
        Sheet sheet = workbook.getSheetAt(0);
        Bom bom = null;
        Row row = null;
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            row = sheet.getRow(i);
            if (row == null) break;
            bom = new Bom();
            bom.setName(getStringCellValue(row.getCell(0)));
            bom.setParamType(getStringCellValue(row.getCell(1)));
            bom.setLabel(getStringCellValue(row.getCell(2)));
            bom.setDesc(getStringCellValue(row.getCell(3)));
            //空行结束
            if (StringUtils.isEmpty(bom.getName()) && StringUtils.isEmpty(bom.getParamType()) && StringUtils.isEmpty(bom.getLabel())) {
                break;
            }
            bom.setBomFields(new ArrayList<BomField>());
            boms.put(bom.getName(), bom);

        }
        //2.解析field表
        if (workbook.getNumberOfSheets() < 2) {
            throw new IllegalStateException("Excel中变量为空");
        }
        sheet = workbook.getSheetAt(1);
        List<BomField> bomFields = null;
        BomField field = null;
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            row = sheet.getRow(i);
            field = new BomField();
            String id = getStringCellValue(row.getCell(0));
            if (StringUtils.isEmpty(id)) {
                id = StringUtils.generateShortUuid();
            } else if (!id.matches(".*\\p{Alpha}.*")) {
                throw new IllegalStateException("第" + (i + 1) + "行,id值要包含字母");
            }
            field.setId(id);
            field.setClassName(getStringCellValue(row.getCell(1)));
            field.setName(getStringCellValue(row.getCell(2)));
            field.setType(getStringCellValue(row.getCell(3)));
            field.setLabel(getStringCellValue(row.getCell(4)));
            field.setDesc(getStringCellValue(row.getCell(5)));
            field.setDomain(getStringCellValue(row.getCell(6)));
            field.setDomainStr(getStringCellValue(row.getCell(7)));
            field.setCollection(getStringCellValue(row.getCell(8)));
            field.setIsout(getStringCellValue(row.getCell(9)));
            field.setPattern(getStringCellValue(row.getCell(10)));
            field.setMathStr(getStringCellValue(row.getCell(11)));
            field.setDefaultValue(getStringCellValue(row.getCell(12)));
            field.setIsDerives(getStringCellValue(row.getCell(13)));
            field.setIsCollections(getStringCellValue(row.getCell(14)));
            field.setDomainId("");
            //验证Domain值合法
            validateDomain(field, doms);
            if (boms.get(field.getClassName()) == null) {
                throw new IllegalStateException("第" + (i + 1) + "行,class列值\"" + field.getClassName() + "\"无效");
            }
            if (StringUtils.isNotBlank(field.getCollection())) {
                String collection = field.getCollection().substring(0, 1).toUpperCase() + field.getCollection().substring(1, field.getCollection().length());
                field.setCollection(collection);
            }
            bomFields = boms.get(field.getClassName()).getBomFields();
            bomFields.add(field);
        }
        return boms;
    }

    /**
     * 解析工作表中的Domain对象
     */
    public static Map<String, Domain> excelToDom(Workbook workbook) {
        if (workbook.getNumberOfSheets() < 3) {
            return null;
        }
        Sheet sheet = workbook.getSheetAt(2);

        Map<String, Domain> doms = new HashMap<String, Domain>();
        Row row = null;
        Domain dom = null;
        List<DomainItem> items = null;
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            row = sheet.getRow(i);
            if (row == null) break;
            String domName = getStringCellValue(row.getCell(1));
            if (StringUtils.isEmpty(domName)) {
            	throw new IllegalStateException("第" + (i + 1) + "行,domain名称为空");
            }
            dom = doms.get(domName);

            if (dom == null) {
                dom = new Domain();
                String id = getStringCellValue(row.getCell(0));
                if (StringUtils.isEmpty(id)) {
                    id = StringUtils.generateShortUuid();
                } else if (!id.matches(".*\\p{Alpha}.*")) {
                    throw new IllegalStateException("第" + (i + 1) + "行,id值要包含字母");
                }
                dom.setId(id);
                dom.setName(getStringCellValue(row.getCell(1)));
                dom.setDataType(getStringCellValue(row.getCell(3)));
                dom.setLabel(getStringCellValue(row.getCell(4)));
                dom.setDesc(getStringCellValue(row.getCell(5)));
                dom.setAttrId("");
                items = new ArrayList<DomainItem>();
                dom.setDomainItems(items);
                doms.put(domName, dom);
            } else {
                items = dom.getDomainItems();
            }

            DomainItem it = new DomainItem();
            String itId = getStringCellValue(row.getCell(2));
            if (StringUtils.isEmpty(itId)) {
                itId = StringUtils.generateShortUuid();
            }
            it.setId(itId);
            it.setName(getStringCellValue(row.getCell(6)));
            it.setValue(getStringCellValue(row.getCell(7)));
            items.add(it);
        }
        return doms;
    }

    /**
     * 验证domain合法性以及关联domain对应的field
     */
    private static void validateDomain(BomField field, Map<String, Domain> doms) {
        //System.out.println("domain值 ："+field.getDomain()+","+field.getDomainStr());
        if (field.getDefaultValue() == null && !field.getIsCollections().equals("true")) {
        	if("String".equals(field.getDataType())){
        		field.setDefaultValue("");
        	}else {
            	String error = "field:\"" + field.getName() + "\"默认值为空";
            	logger.error(error);
                throw new IllegalStateException(error);
        	}
        }
        boolean hasDomain = false;
        if (!StringUtils.isEmpty(field.getDomain())) {
            if (field.getDomain().startsWith("[") || field.getDomain().startsWith("(")) {
                //数字或日期范围类型,无关联domain
                hasDomain = false;
            } else {
                hasDomain = true;
                //有引用Domain,类型要为String
                if (!"String".equals(field.getType())) {
                    field.setType("String");
                }
                if (doms == null || !doms.containsKey(field.getDomain())) {
                    throw new IllegalStateException("domain值\"" + field.getDomain() + "\"无效");
                } else {
                    field.setDomainId(doms.get(field.getDomain()).getId());
                    doms.get(field.getDomain()).setAttrId(field.getId());
                }

            }

        }

        if (!StringUtils.isEmpty(field.getDomainStr()) && hasDomain) {
            if (StringUtils.isEmpty(field.getDomain())) {
                throw new IllegalStateException("domainStr值\"" +
                        field.getDomainStr() + "\"对应的domain为空");
            }
            List<DomainItem> items = doms.get(field.getDomain()).getDomainItems();
            String[] domAry = field.getDomainStr().trim().replaceAll("[\\[\\]]", "").split(",");
            boolean valid = true;
            for (String str : domAry) {
                valid = false;
                for (DomainItem e : items) {
                    if (str.trim().equals(e.getName())) {
                        valid = true;
                        break;
                    }
                }
                if (!valid) {
                    throw new IllegalStateException("domainStr值\"" +
                            field.getDomainStr() + "\"中的\"" + str
                            + "\"无效");
                }

            }

        }

    }

    private static String getStringCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        int type = cell.getCellType();
        if (type == Cell.CELL_TYPE_BLANK) {
            return "";
        } else if (type == Cell.CELL_TYPE_STRING) {
            return cell.getStringCellValue();
        } else if (type == Cell.CELL_TYPE_NUMERIC) {
            double val = cell.getNumericCellValue();
            int i = (int) val;
            if (val - i > 0) {
                return val + "";
            } else {
                return MathUtil.formatDouble(val, 0);
            }

        } else if (type == Cell.CELL_TYPE_BOOLEAN) {
            return cell.getBooleanCellValue() + "";
        }
        return "";
    }

    public void upload(MultipartFile file, String projectCode, String datamodelid,String userId, String rankRelationId) throws Exception {
        excelToXml(file, projectCode, datamodelid, userId, rankRelationId);
    }

    /**
     * 将xml文件转化成excel下载
     */
    public Workbook download(String path, String projectCode, String datamodelid, String rankRelationId) throws Exception {
        // 声明一个工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 设置这些样式
        HSSFCellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(HSSFColor.LIGHT_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        //设置字体
        HSSFFont font = workbook.createFont();
        // font.setColor(HSSFColor.BLUE_GREY.index);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        style.setFont(font);

        // 生成class表
        HSSFSheet sheet = workbook.createSheet("class");
        // 产生表格标题行
        HSSFRow row = sheet.createRow(0);
        String headers[] = {"name", "paramType", "chzn", "desc"};
        int i = 0;
        for (i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(style);
            cell.setCellValue(new HSSFRichTextString(headers[i]));
        }

//		Map<String, MClass> dsMap = RuleBomMapXmlConvert.getMapping(mappingFile);
//		Map<String, MClass> boms = dsMap;
        Map<String, MClass> boms = dataBomService.findMapClassByDataModelId(projectCode,"0",datamodelid,rankRelationId);

        boms.remove("SYS_RULE");

        i = 1;
        for (String key : boms.keySet()) {
            MClass m = boms.get(key);
            row = sheet.createRow(i++);
            HSSFCell cell = row.createCell(0);
            cell.setCellValue(m.getName());
            cell = row.createCell(1);
            cell.setCellValue(m.getParamType());
            cell = row.createCell(2);
            cell.setCellValue(m.getChzn());
            cell = row.createCell(3);
            cell.setCellValue(m.getDesc());
        }
        //生成field表
        sheet = workbook.createSheet("field");
        row = sheet.createRow(0);
        headers = new String[]{"id", "class", "name", "type", "chzn", "desc", "domain",
                "domainStr", "collection", "isout", "pattern", "mathStr",
                "defaultValue", "isDerives", "isCollections"};
        for (i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(style);
            cell.setCellValue(new HSSFRichTextString(headers[i]));
        }
        i = 1;
        Map<String, Domain> domainMap = dataBomService.findDomainByProjectCode(projectCode);
        List<Domain> domainList = new ArrayList<Domain>();
        for (String key : boms.keySet()) {
            MClass m = boms.get(key);
            Map<String, MField> fieldMap = m.getFieldMap();
            for (String k : fieldMap.keySet()) {
            	MField f = fieldMap.get(k);
            	if( !"1".equals(f.getIsfuncparam()) ) {
	                row = sheet.createRow(i++);
	                if(	domainMap.containsKey(f.getId()) ) {
	                	domainList.add(domainMap.get(f.getId()));
	                }
	                row.createCell(0).setCellValue(f.getId());
	                row.createCell(1).setCellValue(m.getName());
	                row.createCell(2).setCellValue(f.getName());
	                row.createCell(3).setCellValue(f.getType());
	                row.createCell(4).setCellValue(f.getChzn());
	                row.createCell(5).setCellValue(f.getDesc());
	                row.createCell(6).setCellValue(f.getDomain());
	                row.createCell(7).setCellValue(f.getDomainStr());
	                row.createCell(8).setCellValue(f.getCollection());
	                row.createCell(9).setCellValue(f.getIsout());
	                row.createCell(10).setCellValue(f.getPattern());
	                row.createCell(11).setCellValue(f.getMathStr());
	                HSSFCell hcell = row.createCell(12);
	                hcell.setCellValue(f.getDefaultValue());
	                if("String_Date".contains(f.getType())) {
	                	hcell.setCellType(HSSFCell.CELL_TYPE_STRING);
	                }
	                row.createCell(13).setCellValue(f.getIsDerives());
	                row.createCell(14).setCellValue(f.getIsCollections());
            	}
            }

        }
        //生成field表
        sheet = workbook.createSheet("domain");
        row = sheet.createRow(0);
        headers = new String[]{"id", "name", "childId", "type", "chzn", "desc", "item name", "item value"};
        for (i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(style);
            cell.setCellValue(new HSSFRichTextString(headers[i]));
        }
        i = 1;
        
        for (Domain dom : domainList) {
            for (DomainItem di : dom.getDomainItems()) {
                row = sheet.createRow(i++);
                row.createCell(0).setCellValue(di.getId());
                row.createCell(1).setCellValue(dom.getId());
                row.createCell(2).setCellValue(di.getId());
                row.createCell(3).setCellValue(dom.getType());
                row.createCell(4).setCellValue(dom.getLabel());
                row.createCell(5).setCellValue(dom.getDesc());
                row.createCell(6).setCellValue(di.getName());
                row.createCell(7).setCellValue(di.getValue());
            }
        }

        // 生成ruleenum表
 		sheet = workbook.createSheet("ruleenum");
 		row = sheet.createRow(0);
 		headers = new String[] { "id", "enumName", "enumCode", "enumType" };
 		for (i = 0; i < headers.length; i++) {
 			HSSFCell cell = row.createCell(i);
 			cell.setCellStyle(style);
 			cell.setCellValue(new HSSFRichTextString(headers[i]));
 		}
 		i = 1;
 		List<RuleEnum> ruleenumlist = dataBomService.findRuleEnumByProjectCode(projectCode);
 		for (RuleEnum list : ruleenumlist) {
 			row = sheet.createRow(i++);
 			row.createCell(0).setCellValue(list.getId());
 			row.createCell(1).setCellValue(list.getEnumName());
 			row.createCell(2).setCellValue(list.getEnumCode());
 			row.createCell(3).setCellValue(list.getEnumType());
 		}

 		// 生成ruleenumtype表
 		sheet = workbook.createSheet("ruleenumtype");
 		row = sheet.createRow(0);
 		headers = new String[] { "id", "name", "domainValue" };
 		for (i = 0; i < headers.length; i++) {
 			HSSFCell cell = row.createCell(i);
 			cell.setCellStyle(style);
 			cell.setCellValue(new HSSFRichTextString(headers[i]));
 		}
 		i = 1;
 		List<RuleEnum> ruleenumtype = dataBomService.findRuleEnumTypeByProjectCode(projectCode);
 		for (RuleEnum list : ruleenumtype) {
 			row = sheet.createRow(i++);
 			row.createCell(0).setCellValue(list.getId());
 			row.createCell(1).setCellValue(list.getEnumName());
 			row.createCell(2).setCellValue(list.getEnumCode());
 		}
 		return workbook;
 	}


    //格式化日期值
//	private static MField dateFormat(MField mField) throws  Exception{
//		if(DATE.equals(mField.getType())){
//			MField target = new MField();
//			BeanUtils.copyProperties(mField, target);
//			String pattern = DEFAULT_PATTERN;
//			if(StringUtils.isBlank(target.getPattern())){
//				target.setPattern(pattern);
//			}else{
//				pattern = target.getPattern();
//			}
//			pattern = pattern.replaceAll("Y", "y").replaceAll("D","d");
//			SimpleDateFormat sf = new SimpleDateFormat(pattern);
//			try{
//				 Date time = new Date(Long.parseLong(target.getDefaultValue()));
//				 target.setDefaultValue(sf.format(time));
//				 if(StringUtils.isNotBlank(target.getDomain())){
//					 String[] bounds = target.getDomain().split(",|，");
//					 String start = bounds[0].trim().substring(1, bounds[0].length());
//					 String end = bounds[1].trim().substring(0, bounds[1].length()-1);
//					 start = StringUtils.isNotBlank(start)? sf.format(new Date(Long.parseLong(start))):"";
//					 end = StringUtils.isNotBlank(end)? sf.format(new Date(Long.parseLong(end))):"";
//					 target.setDomain("["+start+","+end+"]");
//				 }
//			}catch(Exception e){
//				e.printStackTrace();
//			}
//			return target;
//		}else{
//			return mField;
//		}
//	}


    //日期值to Long
//	private static BomField timeToLong(BomField mField) throws Exception{
//		if(DATE.equals(mField.getType())){
//			BomField target = new BomField();
//			BeanUtils.copyProperties(mField, target);
//			String defaultValue = target.getDefaultValue();
//			String domain = target.getDomain();
//			if(StringUtils.isBlank(domain) || StringUtils.isBlank(defaultValue)){
//				return mField;
//			}
//			
//			String pattern = DEFAULT_PATTERN;
//			if(StringUtils.isBlank(target.getPattern())){
//				target.setPattern(pattern);
//			}else{
//				pattern = target.getPattern();
//			}
//			
//			pattern = pattern.replaceAll("Y", "y").replaceAll("D", "d");
//			SimpleDateFormat sf = new SimpleDateFormat(pattern);
//			try {
//				target.setDefaultValue(sf.parse(defaultValue).getTime() + "");
//			} catch (Exception e) {
//				throw new IllegalStateException("defaultValue值\"" + mField.getDefaultValue() + "\"无效");
//			}
//			try{	
//				String[] bounds = target.getDomain().split(",|，");
//				String start = bounds[0].trim().substring(1, bounds[0].length());                             
//				String end = bounds[1].trim().substring(0, bounds[1].length()-1);
//				start = StringUtils.isNotBlank(start)? sf.parse(start).getTime()+"":"";         
//				end = StringUtils.isNotBlank(end)? sf.parse(end).getTime()+"":"";
//				
//				if(StringUtils.isNotBlank(start) && StringUtils.isNotBlank(end) && new Date(Long.parseLong(start)).compareTo(new Date(Long.parseLong(end))) >0){
//					throw new IllegalStateException();
//				}else{
//					target.setDomain("["+start+","+end+"]");
//				}
//			}catch(Exception e){
//				throw new IllegalStateException("domain值\""+mField.getDomain()+"\"无效");
//			}
//			return target;
//		}else{
//			return mField;
//		}
//	}


    /**
     * 解析ruleDomain.xml文件中的Domain对象
     */
    public static List<Domain> getDomainList(File domainFile) {

        XMLHandler xmlHandler = new XMLHandler(domainFile, "UTF-8");
        Element rootElement = xmlHandler.getRootElement();
        List listTopObj = rootElement.elements("domain");
        List<Domain> domainList = new ArrayList<Domain>();
        for (Iterator iterator = listTopObj.iterator(); iterator.hasNext(); ) {
            Element topObj = (Element) iterator.next();
            Domain dom = new Domain();
            dom.setId(topObj.attributeValue("id"));
            dom.setName(topObj.attributeValue("name"));
            dom.setLabel(topObj.attributeValue("chzn"));
            dom.setDataType(topObj.attributeValue("type"));
            dom.setDesc(topObj.attributeValue("desc"));
            dom.setDomainItems(new ArrayList<DomainItem>());

            List fieldsObj = topObj.elements("item");
            for (Iterator iterator2 = fieldsObj.iterator(); iterator2.hasNext(); ) {
                Element mF = (Element) iterator2.next();
                DomainItem di = new DomainItem();
                di.setId(mF.attributeValue("id"));
                di.setName(mF.attributeValue("name"));
                di.setValue(mF.attributeValue("value"));
                dom.getDomainItems().add(di);
            }

            domainList.add(dom);
        }
        return domainList;
    }

}
